#include <climits>

#include "topcvt_policycontext.hpp"
#include "topcvt_policyhelper.hpp"
#include "fixed_unpack.hpp"
#include "fixed_helper.hpp"

namespace topcvt
{
    void FixedUnpack::checkElementCfgValid(AttributeableCfg& t)
    {
        if (t.getCfgType() == cfgtype_t::E_POLICY )
        {
            check(t);
        }
        else if (t.getCfgType() == cfgtype_t::E_FIELD)
        {
            string fldval = t.get(ATTR_LEN);
            int sLen = topcvt_string::to_int<string>(fldval);
            PolicyHelper::checkIntRange(t, ATTR_LEN, -1, INT_MAX);
            PolicyHelper::checkIntRange(t, ATTR_OFFSET, -1, INT_MAX);
            check(t);
        }
    }

    void FixedUnpack::check(AttributeableCfg& t)
    {
        PolicyHelper::checkValidRange(t, "fillType", { "byte", "char" });
        PolicyHelper::checkValidRange(t, "fillLocation", { "left", "right" });
    }

    string FixedUnpack::unpackField(pugi::xml_node& node, FieldCfg& f, PolicyContext& ctx)
    {
        string value("");
        string variant = f.getName();
        string sLen = f.get(ATTR_LEN);

        int len = topcvt_string::to_int<string>(sLen);
        TLOG_TRACE("field:name=%s len=%d",variant.c_str(),len);

        if (len != 0)
        {
            if (len == -1) 
            {
                len = m_message.remaining();
            }
            string sOffset = f.get(ATTR_OFFSET);
            int offset = topcvt_string::to_int<string>(sOffset);
            if (offset != -1) 
            {
                if(offset > 0) m_message.position(offset);
                value = m_message.get(len);
                if (value.size() != 0)
                {
                    string fillType = ctx.getNodeAttr(f, "fillType", "char");
                    string fillLocation = ctx.getNodeAttr(f, "fillLocation", DEFAULT_FILL_LOCATION);
                    bool left = true;
                    if (fillLocation == "right")
                        left = false;
                    char ch = 0;
                    if (fillType == "char")
                    {
                        string fillChar = ctx.getNodeAttr(f, "fillChar", " ");
                        ch = fillChar[0];
                    }
                    else if (fillType == "byte") 
                    {
                        string fillChar = ctx.getNodeAttr(f, "fillChar", "0");
                        ch = topcvt_string::to_int<string>(fillChar);
                    }

                    if (left)
                        topcvt_string::removechar_left(value,ch);
                    else
                        topcvt_string::removechar_right(value, ch);
                }
            }
        }
        value = PolicyHelper::getUnpackFieldValue(ctx, f, value);
        if (!variant.empty())
        {
            TLOG_DEBUG("field:%s <--[%d][%s]", variant.c_str(), len, value.c_str());
            PolicyContext::setFldVal(ctx, variant, value);
        }
        return value;
    }
};